#ifndef _VL_TUNNEL__H_
#define _VL_TUNNEL__H_

#include "wrapper/tunnel_message.h"
#include "tunnel/vl_terminator.h"

#include <memory>

namespace VL {

/**
 * @Author: CimZzz
 * @Date: 2022-07-14 17:21:56
 * 
 * 管道基类
 * 管道可以看做是一个数据通道, 在逻辑上划分为数据入口和出口, 可以双向传输数据, 并针对数据进行加工
 * 
 * * 数据的传递与回复, 只是在逻辑上进行的划分, 表示数据流动方向, 无其他实际意义
 * 
 * pass  : 表示向下数据管道传递
 * reply : 表示向上数据管道回复
 */
class BaseTunnel {
protected:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 17:24:20
	 * 
	 * 构造方法, 不允许实例化, 仅支持子类继承
	 */
	explicit BaseTunnel();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-19 16:10:42
	 * 
	 * 析构方法, 如果存在上级管道和下级管道, 则会将其连接起来
	 */
	~BaseTunnel();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 17:46:18
	 * 
	 * 向下级通道传递消息
	 * 
	 * @param message 通道消息指针引用
	 * 
	 * @note 如果下级通道不存在, 则该方法无效果
	 */
	void passMessage(const std::shared_ptr<TunnelMessage>& message);
	
	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 19:35:11
	 * 
	 * 向上级通道回复消息
	 * 
	 * @param message 通道消息指针引用
	 * 
	 * @note 如果上级通道不存在, 则该方法无效果
	 */
	void replyMessage(const std::shared_ptr<TunnelMessage>& message);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 12:02:33
	 * 
	 * 向下级管道传递数据
	 * @param data 数据指针
	 */
	void passData(const std::shared_ptr<TunnelData>& data);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 12:02:33
	 * 
	 * 向上级管道回复数据
	 * @param data 数据指针
	 */
	void replyData(const std::shared_ptr<TunnelData>& data);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 17:25:09
	 * 
	 * 传递数据方法
	 * @param data 管道数据
	 * 
	 * @note 通过参数中的数据块获取数据进行处理, 可以选择继续向下传递或者抛出异常交由上/下线 Tunnel 处理
	 */
	virtual void doPass(const std::shared_ptr<TunnelData>& data);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 17:25:14
	 * 
	 * 回复数据方法
	 * @param data 管道数据
	 * 
	 * @note 通过参数中的数据块获取数据进行处理, 可以选择继续向上回复或者抛出异常交由上/下线 Tunnel 处理
	 */
	virtual void doReply(const std::shared_ptr<TunnelData>& data);

public:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 17:42:15
	 * 
	 * 连接下一个管道
	 * @param tunnel 管道指针
	 * @return 返回下一级管道
	 */
	BaseTunnel* connect(BaseTunnel* tunnel);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-19 17:22:58
	 * 
	 * 输出到指定终端
	 * @param terminator 终端指针
	 */
	void output(Terminator* terminator);

private:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 12:08:05
	 * 
	 * 声明友元
	 */
	friend class Terminator;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 12:05:56
	 * 
	 * 管道入口终端
	 */
	Terminator* inTerminator;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 12:06:24
	 * 
	 * 管道出口终端
	 */
	Terminator* outTerminator;
 
	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 11:53:00
	 * 
	 * 上一级管道
	 */
	BaseTunnel* lastTunnel;
	
	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 11:53:14
	 * 
	 * 下一级管道
	 */
	BaseTunnel* nextTunnel;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-19 17:24:46
	 * 
	 * 重置当前管道到独立状态
	 * 
	 * @attention 直接将链中该管道断开，不会重连前后管道与终端
	 */
	void resetAll();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-19 17:24:27
	 * 
	 * 销毁全部管道
	 * 自动回收内存, 不需要再次 delete
	 * 
	 * @note 可以从管道中任意一点开始, 将整个管道链路（包括终端）全部销毁
	 */
	void destroyAll();
};

}

#endif // _VL_TUNNEL__H_
